package top.z.work.framework.common.exception;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 异常工具类
 */
@Slf4j
public class ExceptionUtil {

    /**
     * 错误码提示模板
     */
    private static final ConcurrentMap<Integer, String> MESSAGE = new ConcurrentHashMap<>();

    public static void put(Integer code, String message) {
        ExceptionUtil.MESSAGE.put(code, message);
    }

    public static void delete(Integer code, String message) {
        ExceptionUtil.MESSAGE.remove(code, message);
    }

    public static ServiceException exception(ErrorCode errorCode) {
        String message = MESSAGE.getOrDefault(errorCode.code(), errorCode.message());
        return exception0(errorCode.code(), message);
    }

    public static ServiceException exception(ErrorCode errorCode, Object... param) {
        String message = MESSAGE.getOrDefault(errorCode.code(), errorCode.message());
        return exception0(errorCode.code(), message, param);
    }

    /**
     * 创建指定编号的 ServiceException 的异常
     *
     * @param code 编号
     * @return 异常
     */
    public static ServiceException exception(Integer code) {
        return exception0(code, MESSAGE.get(code));
    }

    /**
     * 创建指定编号的 ServiceException 的异常
     *
     * @param code  编号
     * @param param 消息提示的占位符对应的参数
     * @return 异常
     */
    public static ServiceException exception(Integer code, Object... param) {
        return exception0(code, MESSAGE.get(code), param);
    }

    public static ServiceException exception0(Integer code, String message, Object... param) {
        return new ServiceException(code, format(code, message, param));
    }

    /**
     * 格式化错误信息
     *
     * @param code    错误编码
     * @param message 错误信息
     * @param param   参数
     * @return 消息
     */
    public static String format(int code, String message, Object... param) {
        StringBuilder sb = new StringBuilder();
        int           i  = 0;
        int           j;
        int           l;
        for (l = 0; l < param.length; l++) {
            j = message.indexOf("{}", i);
            if (j == -1) {
                log.error("[format][参数过多: 错误码({}) | 错误内容({}) | 参数({})", code, message, param);
                if (i == 0) {
                    return message;
                } else {
                    sb.append(message.substring(i));
                    return sb.toString();
                }
            } else {
                sb.append(message, i, j);
                sb.append(param[l]);
                i = j + 2;
            }
        }
        if (message.indexOf("{}", i) != -1) {
            log.error("[doFormat][参数过少：错误码({})|错误内容({})|参数({})", code, message, param);
        }
        sb.append(message.substring(i));
        return sb.toString();
    }

}
